/*
 * ******************************************************************************
 *  * Copyright (c) Jerges A. Bello G. 2014. Reservado todos los derechos.
 *  *****************************************************************************
 */

package com.jabex.core.rest.yahoo;


import java.io.IOException;
import java.io.StringReader;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.log4j.Logger;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import com.jabex.common.exceptions.ErrorFunctionalException;
import com.jabex.common.exceptions.ErrorOperationalException;
import com.jabex.common.exceptions.WarningFunctionalException;
import com.jabex.common.util.Constants;
import com.jabex.core.util.ConstantsMessage;

/**
 * Created by jaugusto on 16/10/14. *
 */
public class YahooGet {
	static private Logger logger = Logger.getLogger(YahooGet.class);

	public static final String queryBaseYahoo = "https://query.yahooapis.com/v1/public/yql?q=";
	private DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
	private static Document document;

	/**
	 * load parameters
	 *
	 * @param result XML response
	 */
	private void initParser(String result) {
		domFactory.setNamespaceAware(true);
		DocumentBuilder builder;
		try {
			builder = domFactory.newDocumentBuilder();
			document = builder.parse(new InputSource(new StringReader(result)));
		} catch (ParserConfigurationException e) {
			throw new ErrorOperationalException(Constants.NAME_APP_CORE, Constants.CODE_APP_CORE, e.getMessage(),
					Constants.TYPE_ORIGIN.API.name(), Constants.TYPE_CHANNELS.REST.name(), e.getLocalizedMessage(), Constants.TYPE_TRANSACTION.GET.name(), null);
		} catch (SAXException e) {
			throw new ErrorOperationalException(Constants.NAME_APP_CORE, Constants.CODE_APP_CORE, e.getMessage(),
					Constants.TYPE_ORIGIN.API.name(), Constants.TYPE_CHANNELS.REST.name(), e.getLocalizedMessage(), Constants.TYPE_TRANSACTION.GET.name(), null);
		} catch (IOException e) {
			throw new ErrorOperationalException(Constants.NAME_APP_CORE, Constants.CODE_APP_CORE, e.getMessage(),
					Constants.TYPE_ORIGIN.API.name(), Constants.TYPE_CHANNELS.REST.name(), e.getLocalizedMessage(), Constants.TYPE_TRANSACTION.GET.name(), null);
		}
	}


	/**
	 * execute Request to Yahoo API
	 *
	 * @param query to execute
	 * @return response data from yahoo
	 * @throws WarningFunctionalException
	 * @throws ErrorFunctionalException
	 * @throws ErrorOperationalException
	 */
	private static String executeRequest(String query) throws ErrorOperationalException, ErrorFunctionalException, WarningFunctionalException {
		HttpClient client = new HttpClient();
		GetMethod method = new GetMethod(query);
		String result;
		// Send GET request
		try {
			int statusCode = client.executeMethod(method);
			switch (statusCode) {
				case Constants.BAD_REQUEST: {
					throw new ErrorFunctionalException(Constants.NAME_APP_CORE, Constants.CODE_APP_CORE, ConstantsMessage.BAD_REQUEST_YAHOO,
							Constants.TYPE_ORIGIN.API.name(), Constants.TYPE_CHANNELS.REST.name(), null, Constants.TYPE_TRANSACTION.GET.name(), null);
				}

				case Constants.PAGE_FORBIDDEN: {
					throw new ErrorFunctionalException(Constants.NAME_APP_CORE, Constants.CODE_APP_CORE, ConstantsMessage.PAGE_FORBIDDEN_YAHOO,
							Constants.TYPE_ORIGIN.API.name(), Constants.TYPE_CHANNELS.REST.name(), null, Constants.TYPE_TRANSACTION.GET.name(), null);
				}

				case Constants.SERVICE_UNAVAILABLE: {
					throw new WarningFunctionalException(Constants.NAME_APP_CORE, Constants.CODE_APP_CORE, ConstantsMessage.SERVICE_UNAVAILABLE_YAHOO,
							Constants.TYPE_ORIGIN.API.name(), Constants.TYPE_CHANNELS.REST.name(), null, Constants.TYPE_TRANSACTION.GET.name(), null);
				}
				default:
			}
			result = method.getResponseBodyAsString();

		} catch (IOException e) {
			throw new ErrorOperationalException(Constants.NAME_APP_CORE, Constants.CODE_APP_CORE, e.getMessage(),
					Constants.TYPE_ORIGIN.API.name(), Constants.TYPE_CHANNELS.REST.name(), e.getLocalizedMessage(), Constants.TYPE_TRANSACTION.GET.name(), null);
		}
		return result;
	}

	/**
	 * Get Countries from Yahoo API
	 */
	public void getCountries() {
		String queryCountries = queryBaseYahoo + "select%20*%20from%20geo.countries&diagnostics=true&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys";
		try {
			String result = executeRequest(queryCountries);
			initParser(result);
			NodeList results = document.getElementsByTagName("place");
			if(results.getLength() >0) {
				Node unContacto = results.item(0);
				if (unContacto.getNodeType() == Node.ELEMENT_NODE) {
					Element elemento = (Element) unContacto;
					System.out.println(elemento.getAttribute("name"));
				}
			}else{
				logger.info("No hay Paises que mostrar");
			}
		} catch (ErrorOperationalException e) {
			logger.fatal(e.getMessage());
		} catch (ErrorFunctionalException e) {
			logger.error(e.getMessage());
		} catch (WarningFunctionalException e) {
			logger.warn(e.getMessage());
		} catch (DOMException e) {
			logger.fatal(e.getMessage());
			throw new ErrorOperationalException(Constants.NAME_APP_CORE, Constants.CODE_APP_CORE, e.getMessage(),
					Constants.TYPE_ORIGIN.API.name(), Constants.TYPE_CHANNELS.REST.name(), e.getLocalizedMessage(), Constants.TYPE_TRANSACTION.GET.name(), null);
		}

	}

	/**
	 * Get finance quote from Yahoo API
	 */
	public void getFinanceQuote() {
		String request = queryBaseYahoo + "select%20*%20from%20yahoo.finance.quote%20where%20symbol%20in%20(%22YHOO%22%2C%22AAPL%22%2C%22GOOG%22%2C%22MSFT%22)&diagnostics=true&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys";
		try {
			String result = executeRequest(request);
			initParser(result);
			NodeList results = document.getElementsByTagName("place");
			if(results.getLength() >0) {
				Node unContacto = results.item(0);
				if (unContacto.getNodeType() == Node.ELEMENT_NODE) {
					Element elemento = (Element) unContacto;
					System.out.println(elemento.getAttribute("name"));
				}
			}else{
				logger.info("No hay datos financieros que mostrar");
			}
		} catch (ErrorOperationalException e) {
			logger.fatal(e.getMessage());
		} catch (ErrorFunctionalException e) {
			logger.error(e.getMessage());
		} catch (WarningFunctionalException e) {
			logger.warn(e.getMessage());
		} catch (DOMException e) {
			logger.fatal(e.getMessage());
			throw new ErrorOperationalException(Constants.NAME_APP_CORE, Constants.CODE_APP_CORE, e.getMessage(),
					Constants.TYPE_ORIGIN.API.name(), Constants.TYPE_CHANNELS.REST.name(), e.getLocalizedMessage(), Constants.TYPE_TRANSACTION.GET.name(), null);
		}
	}

	/**
	 * Get finance sector from Yahoo API
	 */
	public void getFinanceSector() {
		String request = queryBaseYahoo + "select%20*%20from%20yahoo.finance.sectors&diagnostics=true&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys";
		try {
			String result = executeRequest(request);
			initParser(result);
			NodeList results = document.getElementsByTagName("place");
			if(results.getLength() >0) {
				Node unContacto = results.item(0);
				if (unContacto.getNodeType() == Node.ELEMENT_NODE) {
					Element elemento = (Element) unContacto;
					System.out.println(elemento.getAttribute("name"));
				}
			}else{
				logger.info("No hay sectores financieros que mostrar");
			}
		} catch (ErrorOperationalException e) {
			logger.fatal(e.getMessage());
		} catch (ErrorFunctionalException e) {
			logger.error(e.getMessage());
		} catch (WarningFunctionalException e) {
			logger.warn(e.getMessage());
		} catch (DOMException e) {
			logger.fatal(e.getMessage());
			throw new ErrorOperationalException(Constants.NAME_APP_CORE, Constants.CODE_APP_CORE, e.getMessage(),
					Constants.TYPE_ORIGIN.API.name(), Constants.TYPE_CHANNELS.REST.name(), e.getLocalizedMessage(), Constants.TYPE_TRANSACTION.GET.name(), null);
		}
	}



}
